#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自定义优惠券管理界面
独立于主应用，提供优惠券配置的增删改查功能
"""

import streamlit as st
import pandas as pd
from datetime import datetime, date, timedelta
from typing import List, Dict, Any
import json
import os
import logging
from loguru import logger


from sqlalchemy.engine import create_engine
from sqlalchemy.sql import text  # 导入 text 用于包装 SQL 语句
# 连接 hive 数据库
engine = create_engine('presto://u_algorithm@trino.aihuishou.com:9090/hive/default')

# 数据库表名
table_name = "algo.ahs_customed_coupon"

# 搜索优惠券sql代码
coupon_search_sql = """
    select
        *
    from algo.ahs_customed_coupon
"""

# 数据库表名
table_name = "algo.ahs_customed_coupon"


class CouponManager:
    """优惠券管理器"""
    
    def __init__(self):
        self.data_file = "custom_coupons.json"
        self.channel_options = ["京东", "自营1", "自营2", "自营3"]
        self.category_options = ["手机", "笔记本", "平板电脑", "智能手表", "耳机耳麦"]
        self.operator_options = ["超级管理员", "蔡奇甫", "杨雨", "胡静美", "高杰", "骆意", "丁楚钰", "陈奕璇"]
        self.init_session_state()
    
    def init_session_state(self):
        """初始化会话状态"""
        if 'coupon_data' not in st.session_state:
            st.session_state.coupon_data = self.load_coupon_data()
        
        if 'editing_index' not in st.session_state:
            st.session_state.editing_index = None
        
        if 'selected_operator' not in st.session_state:
            st.session_state.selected_operator = self.operator_options[0]  # 默认选择第一个操作人
        
        if 'search_results' not in st.session_state:
            st.session_state.search_results = []
        
        if 'search_filters' not in st.session_state:
            st.session_state.search_filters = {
                'category': None,
                'channel': None,
                'start_date': None
            }
        
        if 'available_dates' not in st.session_state:
            st.session_state.available_dates = []
    
    def load_coupon_data(self) -> List[Dict[str, Any]]:
        """加载优惠券数据"""
        try:
            if os.path.exists(self.data_file):
                with open(self.data_file, 'r', encoding='utf-8') as f:
                    loaded_data = json.load(f)
                    
                # 兼容旧格式和新格式
                if isinstance(loaded_data, list):
                    # 旧格式：直接是数组
                    return loaded_data
                elif isinstance(loaded_data, dict) and 'data' in loaded_data:
                    # 新格式：包含操作人信息
                    return loaded_data['data']
                else:
                    return []
            return []
        except Exception as e:
            logger.error(f"加载优惠券数据失败: {str(e)}")
            return []
    
    def calculate_total_coupon_price(self, data: List[Dict[str, Any]]) -> float:
        """计算优惠价格总和"""
        total = 0.0
        for row in data:
            try:
                coupon_price = float(row.get('coupon_price', 0))
                total += coupon_price
            except (ValueError, TypeError):
                continue
        return total
    
    def show_save_confirmation(self, data: List[Dict[str, Any]], operator: str) -> bool:
        """显示保存确认对话框"""
        total_price = self.calculate_total_coupon_price(data)
        
        # 使用st.expander创建确认区域
        with st.expander("💰 保存确认 - 点击查看详情", expanded=True):
            st.markdown("### 📊 保存信息汇总")
            
            # 显示详细信息
            col1, col2 = st.columns(2)
            with col1:
                st.metric("优惠价格总和", f"{total_price:.2f} 元")
                st.metric("数据条数", f"{len(data)} 条")
            with col2:
                st.metric("操作人", operator)
                st.metric("保存时间", datetime.now().strftime("%H:%M:%S"))
            
            # 显示详细数据预览
            if data:
                st.markdown("#### 📋 数据预览")
                preview_data = []
                for i, row in enumerate(data):
                    preview_data.append({
                        "序号": i + 1,
                        "生效开始": row.get('start_date', ''),
                        "生效结束": row.get('end_date', ''),
                        "类别": row.get('category', ''),
                        "渠道": row.get('channel', ''),
                        "价格下限": row.get('price_range_min', ''),
                        "价格上限": row.get('price_range_max', ''),
                        "优惠价格": row.get('coupon_price', '')
                    })
                
                if preview_data:
                    st.dataframe(preview_data, use_container_width=True)
            
            st.markdown("---")
            st.warning("⚠️ **请确认操作人是否正确选择？**")
            
            # 确认按钮
            col1, col2, col3 = st.columns([1, 1, 2])
            with col1:
                confirm_save = st.button("✅ 确认保存", type="primary", key="confirm_save")
            with col2:
                cancel_save = st.button("❌ 重新选择", type="secondary", key="cancel_save")
            
            if confirm_save:
                return True
            elif cancel_save:
                return False
        
        return False
    
    def save_coupon_data(self, data: List[Dict[str, Any]], operator: str = None):
        """保存优惠券数据"""
        try:
            logger.info(f"开始保存优惠券数据，数据量: {len(data)} 条，操作人: {operator}")
            # st.info(f"🔄 开始保存优惠券数据，数据量: {len(data)} 条")
            
            # 添加操作人信息到数据中
            save_data = {
                "operator": operator or st.session_state.get('selected_operator', '未知'),
                "save_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "data": data
            }
            
            # 保存到本地JSON文件
            with open(self.data_file, 'w', encoding='utf-8') as f:
                json.dump(save_data, f, ensure_ascii=False, indent=2)
            logger.info(f"优惠券数据保存到本地成功，操作人: {save_data['operator']}")
            st.success("✅ 本地JSON文件保存成功")
            
            # 插入到数据库
            logger.info("开始调用数据库插入函数")
            # st.info("🔄 正在插入数据库...")
            self.insert_coupons_to_database(data, operator)
            
            # 保存成功后清空配置列表
            st.session_state.coupon_data = []
            st.session_state.editing_index = None
            logger.info("优惠券配置列表已清空")
            # st.success("✅ 配置列表已清空")
            
        except Exception as e:
            logger.error(f"保存优惠券数据失败: {str(e)}")
            logger.error(f"异常类型: {type(e).__name__}")
            import traceback
            logger.error(f"异常堆栈: {traceback.format_exc()}")
            st.error(f"保存失败: {str(e)}")
            st.error(f"异常类型: {type(e).__name__}")
    
    def insert_coupons_to_database(self, data: List[Dict[str, Any]], operator: str = None):
        """将优惠券数据插入到数据库"""
        try:
            if not data:
                logger.info("没有数据需要插入数据库")
                st.warning("⚠️ 没有数据需要插入数据库")
                return
            
            logger.info(f"开始插入数据库，数据量: {len(data)} 条")
            # st.info(f"🔄 正在插入数据库，数据量: {len(data)} 条")
            
            # 使用简单的字符串拼接方式插入
            for i, row in enumerate(data):
                logger.info(f"处理第 {i+1} 条数据: {row}")
                
                # 构建单条插入语句
                insert_sql = f"""
                    INSERT INTO algo.ahs_customed_coupon 
                    (partition_date, start_date, end_date, category, channel, coupon_type, 
                     price_range_operator, price_range_min, price_range_max, coupon_price, operator)
                    VALUES ('{row['partition_date']}', '{row['start_date']}', '{row['end_date']}', 
                            '{row['category']}', '{row['channel']}', '{row['coupon_type']}', 
                            '{row['price_range_operator']}', '{row['price_range_min']}', 
                            '{row['price_range_max']}', '{row['coupon_price']}', 
                            '{operator or st.session_state.get('selected_operator', '未知')}')
                """
                
                logger.info(f"执行SQL: {insert_sql}")
                
                # 执行插入操作
                with engine.connect() as connection:
                    logger.info("数据库连接成功，开始执行插入操作")
                    result = connection.execute(text(insert_sql))
                    logger.info(f"第 {i+1} 条数据插入结果: {result}")
                    connection.commit()  # 立即提交
                    logger.info(f"第 {i+1} 条数据提交成功")
                
                logger.info(f"第 {i+1} 条数据插入完成")
            
            logger.info(f"所有数据插入数据库成功！共插入 {len(data)} 条记录")
            st.success(f"✅ 数据已成功插入数据库！共 {len(data)} 条记录")
                
        except Exception as e:
            logger.error(f"数据插入数据库失败: {str(e)}")
            logger.error(f"异常类型: {type(e).__name__}")
            import traceback
            logger.error(f"异常堆栈: {traceback.format_exc()}")
            st.error(f"数据库插入失败: {str(e)}")
            st.error(f"异常类型: {type(e).__name__}")
    
    def search_coupons_from_database(self, category: str = None, channel: str = None, start_date: str = None):
        """从数据库搜索优惠券"""
        try:
            # 构建搜索SQL
            search_sql = "SELECT * FROM algo.ahs_customed_coupon WHERE 1=1"
            params = {}
            
            if category and category != '全部':
                search_sql += " AND category = :category"
                params['category'] = category
            
            if channel and channel != '全部':
                search_sql += " AND channel = :channel"
                params['channel'] = channel
            
            if start_date:
                search_sql += " AND start_date = :start_date"
                params['start_date'] = start_date
            
            search_sql += " ORDER BY partition_date DESC, start_date DESC"
            
            # 执行搜索
            with engine.connect() as connection:
                result = connection.execute(text(search_sql), params)
                columns = result.keys()
                rows = result.fetchall()
                
                # 转换为字典列表
                search_results = []
                for row in rows:
                    row_dict = dict(zip(columns, row))
                    search_results.append(row_dict)
                
                logger.info(f"搜索到 {len(search_results)} 条优惠券记录")
                return search_results
                
        except Exception as e:
            logger.error(f"搜索优惠券失败: {str(e)}")
            st.error(f"搜索失败: {str(e)}")
            return []
    
    def get_available_dates_with_prices(self, category: str, channel: str):
        """根据类别和渠道获取可用的生效开始日期及其优惠价格加和"""
        try:
            # 构建查询SQL，同时计算优惠价格加和
            date_sql = """
                SELECT 
                    start_date,
                    SUM(CAST(coupon_price AS DECIMAL(10,2))) as total_price
                FROM algo.ahs_customed_coupon 
                WHERE 1=1
            """
            params = {}
            
            if category:
                date_sql += " AND category = :category"
                params['category'] = category
            
            if channel:
                date_sql += " AND channel = :channel"
                params['channel'] = channel
            
            date_sql += " GROUP BY start_date ORDER BY start_date DESC"
            
            # 执行查询
            with engine.connect() as connection:
                result = connection.execute(text(date_sql), params)
                date_price_data = []
                for row in result.fetchall():
                    date_price_data.append({
                        'start_date': row[0],
                        'total_price': float(row[1]) if row[1] else 0.0
                    })
                
                logger.info(f"找到 {len(date_price_data)} 个可用日期及其价格信息")
                return date_price_data
                
        except Exception as e:
            logger.error(f"获取可用日期和价格失败: {str(e)}")
            return []
    
    def get_available_dates(self, category: str, channel: str):
        """根据类别和渠道获取可用的生效开始日期（保持向后兼容）"""
        date_price_data = self.get_available_dates_with_prices(category, channel)
        return [item['start_date'] for item in date_price_data]
    
    def add_new_row(self):
        """添加新行"""
        # 获取当天日期
        today = datetime.now().strftime("%Y-%m-%d")
        
        # 如果是第一行，使用默认值；否则继承第一行的字段
        if len(st.session_state.coupon_data) == 0:
            # 第一行使用默认值
            new_row = {
                "partition_date": today,  # 自动填入当天日期
                "start_date": "",
                "end_date": "",
                "category": "手机",  # 默认选择手机
                "channel": "京东",
                "coupon_type": "0",
                "price_range_operator": "between",
                "price_range_min": "",
                "price_range_max": "",
                "coupon_price": ""
            }
        else:
            # 后续行继承第一行的字段
            first_row = st.session_state.coupon_data[0]
            new_row = {
                "partition_date": today,  # 上传日期始终是当天
                "start_date": first_row.get("start_date", ""),
                "end_date": first_row.get("end_date", ""),
                "category": first_row.get("category", "手机"),
                "channel": first_row.get("channel", "京东"),
                "coupon_type": "0",
                "price_range_operator": "between",
                "price_range_min": "",
                "price_range_max": "",
                "coupon_price": ""
            }
        
        st.session_state.coupon_data.append(new_row)
        st.session_state.editing_index = len(st.session_state.coupon_data) - 1
        st.rerun()
    
    def clear_all_data(self):
        """清空所有配置数据"""
        # 检查是否有数据需要清空
        if not st.session_state.coupon_data:
            st.info("📝 配置列表已经是空的，无需清空")
            return
        
        # 记录清空前的数据量
        data_count = len(st.session_state.coupon_data)
        total_price = self.calculate_total_coupon_price(st.session_state.coupon_data)
        
        # 清空配置列表
        st.session_state.coupon_data = []
        st.session_state.editing_index = None
        
        # 记录日志
        logger.info(f"优惠券配置列表已清空，清空了 {data_count} 条数据，总价值 {total_price:.2f} 元")
        
        # 显示成功信息
        st.success(f"✅ 配置列表已清空！共清空 {data_count} 条数据，总价值 {total_price:.2f} 元")
        
        # 强制刷新界面
        st.rerun()
    
    def show_clear_confirmation(self) -> bool:
        """显示清空确认对话框"""
        data_count = len(st.session_state.coupon_data)
        
        if data_count == 0:
            st.info("📝 配置列表已经是空的，无需清空")
            return False
        
        # 使用st.expander创建确认区域
        with st.expander("🗑️ 清空确认 - 点击查看详情", expanded=True):
            st.markdown("### ⚠️ 清空确认")
            
            # 显示要清空的数据信息
            col1, col2 = st.columns(2)
            with col1:
                st.metric("待清空数据条数", f"{data_count} 条")
                total_price = self.calculate_total_coupon_price(st.session_state.coupon_data)
                st.metric("优惠价格总和", f"{total_price:.2f} 元")
            with col2:
                st.metric("操作人", st.session_state.selected_operator)
                st.metric("清空时间", datetime.now().strftime("%H:%M:%S"))
            
            # 显示数据预览
            if st.session_state.coupon_data:
                st.markdown("#### 📋 即将清空的数据预览")
                preview_data = []
                for i, row in enumerate(st.session_state.coupon_data):
                    preview_data.append({
                        "序号": i + 1,
                        "生效开始": row.get('start_date', ''),
                        "生效结束": row.get('end_date', ''),
                        "类别": row.get('category', ''),
                        "渠道": row.get('channel', ''),
                        "价格下限": row.get('price_range_min', ''),
                        "价格上限": row.get('price_range_max', ''),
                        "优惠价格": row.get('coupon_price', '')
                    })
                
                if preview_data:
                    st.dataframe(preview_data, use_container_width=True)
            
            st.markdown("---")
            st.error("⚠️ **此操作将永久删除所有配置数据，且无法恢复！**")
            
            # 确认按钮
            col1, col2, col3 = st.columns([1, 1, 2])
            with col1:
                confirm_clear = st.button("🗑️ 确认清空", type="primary", key="confirm_clear")
            with col2:
                cancel_clear = st.button("❌ 取消清空", type="secondary", key="cancel_clear")
            
            if confirm_clear:
                return True
            elif cancel_clear:
                return False
        
        return False
    
    def delete_row(self, index: int):
        """删除行"""
        if 0 <= index < len(st.session_state.coupon_data):
            st.session_state.coupon_data.pop(index)
            if st.session_state.editing_index == index:
                st.session_state.editing_index = None
            elif st.session_state.editing_index and st.session_state.editing_index > index:
                st.session_state.editing_index -= 1
            st.rerun()
    
    def confirm_row(self, index: int):
        """确认行编辑"""
        st.session_state.editing_index = None
        st.rerun()
    
    def edit_row(self, index: int):
        """编辑行"""
        st.session_state.editing_index = index
        st.rerun()
    
    def validate_row(self, row_data: Dict[str, Any]) -> List[str]:
        """验证行数据"""
        errors = []
        
        # 验证日期格式 - 必须是 xxxx-xx-xx 格式
        date_fields = ['partition_date', 'start_date', 'end_date']
        for field in date_fields:
            if not row_data.get(field):
                errors.append(f"{field} 不能为空")
            else:
                date_str = row_data[field]
                # 检查格式是否为 xxxx-xx-xx
                if not self._is_valid_date_format(date_str):
                    errors.append(f"{field} 格式不正确，必须为 YYYY-MM-DD 格式（如：2025-09-05）")
                else:
                    try:
                        datetime.strptime(date_str, '%Y-%m-%d')
                    except ValueError:
                        errors.append(f"{field} 日期无效")
        
        # 验证类别
        if not row_data.get('category'):
            errors.append("类别不能为空")
        elif row_data.get('category') not in self.category_options:
            errors.append(f"类别必须是以下之一: {', '.join(self.category_options)}")
        
        # 验证价格字段
        price_fields = ['price_range_min', 'price_range_max', 'coupon_price']
        for field in price_fields:
            if not row_data.get(field):
                errors.append(f"{field} 不能为空")
            else:
                try:
                    float(row_data[field])
                except ValueError:
                    errors.append(f"{field} 必须是数字")
        
        # 验证价格范围
        try:
            min_price = float(row_data.get('price_range_min', 0))
            max_price = float(row_data.get('price_range_max', 0))
            if min_price >= max_price:
                errors.append("价格下限必须小于价格上限")
        except (ValueError, TypeError):
            pass
        
        return errors
    
    def _is_valid_date_format(self, date_str: str) -> bool:
        """验证日期格式是否为 xxxx-xx-xx"""
        import re
        # 使用正则表达式验证格式
        pattern = r'^\d{4}-\d{2}-\d{2}$'
        return bool(re.match(pattern, date_str))
    
    def render_search_section(self):
        """渲染搜索功能区域"""
        st.markdown("### 🔍 优惠券搜索")
        st.info("💡 请依次选择类别、渠道和生效开始日期，所有选项都是必填的")
        
        # 搜索条件
        col1, col2, col3, col4 = st.columns([2, 2, 2, 1])
        
        with col1:
            selected_category = st.selectbox(
                "类别筛选 *",
                options=self.category_options,
                index=self.category_options.index(st.session_state.search_filters['category']) if st.session_state.search_filters['category'] in self.category_options else 0,
                key="search_category"
            )
            st.session_state.search_filters['category'] = selected_category
        
        with col2:
            selected_channel = st.selectbox(
                "渠道筛选 *",
                options=self.channel_options,
                index=self.channel_options.index(st.session_state.search_filters['channel']) if st.session_state.search_filters['channel'] in self.channel_options else 0,
                key="search_channel"
            )
            st.session_state.search_filters['channel'] = selected_channel
        
        with col3:
            # 当类别和渠道都选择后，获取可用的日期选项
            if st.session_state.search_filters['category'] and st.session_state.search_filters['channel']:
                # 检查是否需要更新可用日期（避免不必要的数据库查询）
                current_category = st.session_state.search_filters['category']
                current_channel = st.session_state.search_filters['channel']
                
                # 只有当类别或渠道发生变化时才重新查询
                if (not hasattr(st.session_state, 'last_search_category') or 
                    not hasattr(st.session_state, 'last_search_channel') or
                    st.session_state.last_search_category != current_category or
                    st.session_state.last_search_channel != current_channel):
                    
                    # 获取可用日期和价格信息
                    date_price_data = self.get_available_dates_with_prices(current_category, current_channel)
                    st.session_state.date_price_data = date_price_data
                    st.session_state.available_dates = [item['start_date'] for item in date_price_data]
                    st.session_state.last_search_category = current_category
                    st.session_state.last_search_channel = current_channel
                    available_dates = [item['start_date'] for item in date_price_data]
                else:
                    # 使用缓存的数据
                    date_price_data = getattr(st.session_state, 'date_price_data', [])
                    available_dates = getattr(st.session_state, 'available_dates', [])
                
                if available_dates:
                    # 创建带价格信息的选项
                    date_options = []
                    for item in date_price_data:
                        date_str = item['start_date']
                        total_price = item['total_price']
                        display_text = f"{date_str} (总优惠: {total_price})"
                        date_options.append(display_text)
                    
                    # 使用下拉选择框选择日期
                    selected_option = st.selectbox(
                        "生效开始日期 *",
                        options=date_options,
                        index=0 if not st.session_state.search_filters['start_date'] else 
                               next((i for i, item in enumerate(date_price_data) 
                                    if item['start_date'] == st.session_state.search_filters['start_date']), 0),
                        key="search_start_date"
                    )
                    
                    # 提取选中的日期
                    selected_date_str = selected_option.split(' (')[0]
                    st.session_state.search_filters['start_date'] = selected_date_str
                    
                    # 显示选中日期的总优惠价格
                    selected_item = next((item for item in date_price_data if item['start_date'] == selected_date_str), None)
                    if selected_item:
                        st.caption(f"💰 选中日期总优惠价格: {selected_item['total_price']}")
                else:
                    st.warning("⚠️ 当前类别和渠道组合下没有可用的生效开始日期")
                    st.session_state.search_filters['start_date'] = None
            else:
                st.info("请先选择类别和渠道")
                st.session_state.search_filters['start_date'] = None
        
        with col4:
            # 检查是否所有条件都已选择
            can_search = all([
                st.session_state.search_filters['category'],
                st.session_state.search_filters['channel'],
                st.session_state.search_filters['start_date']
            ])
            
            if st.button("🔍 搜索", type="primary", disabled=not can_search):
                # 执行搜索
                search_results = self.search_coupons_from_database(
                    category=st.session_state.search_filters['category'],
                    channel=st.session_state.search_filters['channel'],
                    start_date=st.session_state.search_filters['start_date']
                )
                st.session_state.search_results = search_results
                st.rerun()
            elif not can_search:
                st.caption("请完成所有必填项")
        
        # 显示搜索结果
        if st.session_state.search_results:
            st.markdown("### 📋 搜索结果")
            
            # 显示选中日期的总优惠价格
            if (hasattr(st.session_state, 'date_price_data') and 
                st.session_state.search_filters['start_date']):
                selected_item = next((item for item in st.session_state.date_price_data 
                                    if item['start_date'] == st.session_state.search_filters['start_date']), None)
                if selected_item:
                    st.info(f"💰 **选中日期总优惠价格**: {selected_item['total_price']}")
            
            self.display_search_results(st.session_state.search_results)
        
        st.markdown("---")
    
    def display_search_results(self, results):
        """显示搜索结果"""
        if not results:
            st.info("没有找到匹配的优惠券记录")
            return
        
        # 创建DataFrame显示结果
        df = pd.DataFrame(results)
        
        # 重新排列列的顺序
        column_order = [
            'partition_date', 'start_date', 'end_date', 'category', 'channel',
            'coupon_type', 'price_range_operator', 'price_range_min', 
            'price_range_max', 'coupon_price', 'operator'
        ]
        
        # 确保所有列都存在
        for col in column_order:
            if col not in df.columns:
                df[col] = ''
        
        df_display = df[column_order]
        
        # 重命名列名为中文
        df_display.columns = [
            '分区日期', '生效开始', '生效结束', '类别', '渠道',
            '类型', '方式', '价格下限', '价格上限', '优惠价格', '操作人'
        ]

        # 转换成整数类型再排序
        df_display['价格下限'] = df_display['价格下限'].astype(int)
        df_display['价格上限'] = df_display['价格上限'].astype(int)
        df_display['优惠价格'] = df_display['优惠价格'].astype(int)
        # 按照‘价格下限’ 从小到大排序
        df_sorted = df_display.sort_values(by='价格下限', ascending=True)

        # 显示表格
        st.dataframe(df_sorted, use_container_width=True, hide_index=True)
        
        # 显示统计信息
        st.info(f"共找到 {len(results)} 条记录")
    
    def render_interface(self):
        """渲染管理界面"""
        st.title("🎫 自定义优惠券管理")
        st.markdown("---")
        
        # 搜索功能区域
        self.render_search_section()
        
        # 创建新优惠券区域标识
        st.markdown("### 📝 创建新优惠券")
        st.markdown("---")
        
        # 操作按钮区域
        col1, col2, col3, col4, col5 = st.columns([1, 1, 1, 1, 1])
        
        with col1:
            if st.button("➕ 添加新行", type="primary"):
                self.add_new_row()
        
        with col2:
            # 操作人选择下拉框
            st.session_state.selected_operator = st.selectbox(
                "操作人",
                options=self.operator_options,
                index=self.operator_options.index(st.session_state.selected_operator),
                key="operator_select"
            )
        
        with col3:
            if st.button("💾 保存所有数据", type="secondary"):
                # 验证所有数据
                all_valid = True
                for i, row in enumerate(st.session_state.coupon_data):
                    errors = self.validate_row(row)
                    if errors:
                        st.error(f"第 {i+1} 行数据有误: {', '.join(errors)}")
                        all_valid = False
                
                if all_valid:
                    # 直接保存，不显示确认对话框
                    logger.info("开始直接保存数据，跳过确认对话框")
                    # st.info("🔄 正在保存数据...")
                    self.save_coupon_data(st.session_state.coupon_data, st.session_state.selected_operator)
                    st.success(f"✅ 数据保存成功！操作人: {st.session_state.selected_operator}")
                else:
                    st.warning("⚠️ 请修正错误后再保存")
        
        with col4:
            if st.button("🗑️ 清空所有数据", type="secondary"):
                # 直接清空数据
                if st.session_state.coupon_data:
                    data_count = len(st.session_state.coupon_data)
                    total_price = self.calculate_total_coupon_price(st.session_state.coupon_data)
                    
                    # 清空数据
                    st.session_state.coupon_data = []
                    st.session_state.editing_index = None
                    
                    # 显示成功信息
                    st.success(f"✅ 配置列表已清空！共清空 {data_count} 条数据，总价值 {total_price:.2f} 元")
                    logger.info(f"优惠券配置列表已清空，清空了 {data_count} 条数据，总价值 {total_price:.2f} 元")
                else:
                    st.info("📝 配置列表已经是空的，无需清空")
        
        with col5:
            st.info("💡 提示：点击行末的编辑按钮可修改数据，确认后保存")
        
        st.markdown("---")
        
        # 数据表格
        if not st.session_state.coupon_data:
            st.info("📝 暂无数据，请点击「添加新行」开始配置")
            return
        
        # 表头
        st.markdown("### 📋 优惠券配置列表")
        
        # 列标题
        col_headers = st.columns([1, 1, 1, 1, 1, 0.8, 0.8, 1, 1, 1, 1.2])
        headers = [
            "上传日期", "生效开始", "生效结束", "类别", "渠道", "类型", 
            "方式", "价格下限", "价格上限", "优惠价格", "操作"
        ]
        
        for i, header in enumerate(headers):
            with col_headers[i]:
                st.markdown(f"**{header}**")
        
        st.markdown("---")
        
        # 创建表格
        for i, row in enumerate(st.session_state.coupon_data):
            with st.container():
                # 创建列布局 - 去掉序号列，调整列宽
                cols = st.columns([1, 1, 1, 1, 1, 0.8, 0.8, 1, 1, 1, 1.2])
                
                with cols[0]:
                    # 上传日期不可编辑，始终显示
                    st.text(row.get('partition_date', ''))
                    if st.session_state.editing_index == i:
                        # 在编辑模式下，仍然更新数据但不可编辑
                        row['partition_date'] = row.get('partition_date', '')
                
                with cols[1]:
                    if st.session_state.editing_index == i:
                        row['start_date'] = st.text_input(
                            "生效开始", 
                            value=row['start_date'],
                            key=f"start_date_{i}",
                            placeholder="2025-09-06"
                        )
                    else:
                        st.text(row.get('start_date', ''))
                
                with cols[2]:
                    if st.session_state.editing_index == i:
                        row['end_date'] = st.text_input(
                            "生效结束", 
                            value=row['end_date'],
                            key=f"end_date_{i}",
                            placeholder="2025-09-11"
                        )
                    else:
                        st.text(row.get('end_date', ''))
                
                with cols[3]:
                    if st.session_state.editing_index == i:
                        row['category'] = st.selectbox(
                            "类别",
                            options=self.category_options,
                            index=self.category_options.index(row.get('category', '手机')),
                            key=f"category_{i}"
                        )
                    else:
                        st.text(row.get('category', ''))
                
                with cols[4]:
                    if st.session_state.editing_index == i:
                        row['channel'] = st.selectbox(
                            "渠道",
                            options=self.channel_options,
                            index=self.channel_options.index(row.get('channel', '京东')),
                            key=f"channel_{i}"
                        )
                    else:
                        st.text(row.get('channel', ''))
                
                with cols[5]:
                    if st.session_state.editing_index == i:
                        row['coupon_type'] = st.text_input(
                            "类型", 
                            value=row.get('coupon_type', '0'),
                            key=f"coupon_type_{i}"
                        )
                    else:
                        st.text(row.get('coupon_type', ''))
                
                with cols[6]:
                    if st.session_state.editing_index == i:
                        row['price_range_operator'] = st.text_input(
                            "方式", 
                            value=row.get('price_range_operator', 'between'),
                            key=f"price_range_operator_{i}"
                        )
                    else:
                        st.text(row.get('price_range_operator', ''))
                
                with cols[7]:
                    if st.session_state.editing_index == i:
                        row['price_range_min'] = st.text_input(
                            "价格下限", 
                            value=row.get('price_range_min', ''),
                            key=f"price_range_min_{i}",
                            placeholder="200"
                        )
                    else:
                        st.text(row.get('price_range_min', ''))
                
                with cols[8]:
                    if st.session_state.editing_index == i:
                        row['price_range_max'] = st.text_input(
                            "价格上限", 
                            value=row.get('price_range_max', ''),
                            key=f"price_range_max_{i}",
                            placeholder="399"
                        )
                    else:
                        st.text(row.get('price_range_max', ''))
                
                with cols[9]:
                    if st.session_state.editing_index == i:
                        row['coupon_price'] = st.text_input(
                            "优惠价格", 
                            value=row.get('coupon_price', ''),
                            key=f"coupon_price_{i}",
                            placeholder="50"
                        )
                    else:
                        st.text(row.get('coupon_price', ''))
                
                with cols[10]:
                    if st.session_state.editing_index == i:
                        if st.button("✅", key=f"confirm_{i}", help="确认编辑"):
                            # 验证当前行
                            errors = self.validate_row(row)
                            if errors:
                                st.error(f"数据有误: {', '.join(errors)}")
                            else:
                                self.confirm_row(i)
                    else:
                        col_edit, col_del = st.columns(2)
                        with col_edit:
                            if st.button("✏️", key=f"edit_{i}", help="编辑"):
                                self.edit_row(i)
                        with col_del:
                            if st.button("🗑️", key=f"delete_{i}", help="删除", type="secondary"):
                                self.delete_row(i)
                
                # 减小行间距
                st.markdown("<br>", unsafe_allow_html=True)
        
        # 数据统计
        st.markdown("### 📊 数据统计")
        col1, col2, col3, col4, col5 = st.columns(5)
        
        with col1:
            st.metric("总行数", len(st.session_state.coupon_data))
        
        with col2:
            category_counts = {}
            for row in st.session_state.coupon_data:
                category = row.get('category', '未知')
                category_counts[category] = category_counts.get(category, 0) + 1
            most_common_category = max(category_counts.items(), key=lambda x: x[1]) if category_counts else ("无", 0)
            st.metric("主要类别", f"{most_common_category[0]} ({most_common_category[1]}条)")
        
        with col3:
            channel_counts = {}
            for row in st.session_state.coupon_data:
                channel = row.get('channel', '未知')
                channel_counts[channel] = channel_counts.get(channel, 0) + 1
            most_common_channel = max(channel_counts.items(), key=lambda x: x[1]) if channel_counts else ("无", 0)
            st.metric("主要渠道", f"{most_common_channel[0]} ({most_common_channel[1]}条)")
        
        with col4:
            total_coupons = sum(1 for row in st.session_state.coupon_data if row.get('coupon_price'))
            st.metric("有效优惠券", total_coupons)
        
        with col5:
            st.metric("当前操作人", st.session_state.selected_operator)

def main():
    """主函数"""
    st.set_page_config(
        page_title="优惠券管理",
        page_icon="🎫",
        layout="wide"
    )
    
    # 创建管理器实例
    manager = CouponManager()
    
    # 渲染界面
    manager.render_interface()

if __name__ == "__main__":
    main()


    # 激活环境 source activate ml
    # 启动：nohup streamlit run coupon_manager.py --server.port 8503 --server.address 0.0.0.0 &